/*
 * testIpc.cpp
 *
 *  Created on: 29/07/2014
 *      Author: migue
 */

#include "../comun/ServidorRemoto.h"
#include "../ipcRemoto/SemaforoRemoto.h"
#include "../comun/SalaRemota.h"
#include "../ipcRemoto/MemCompParque.h"
#include "../ipcRemoto/MemCompSala.h"
#include <signal.h>
#include <syslog.h>
#include <unistd.h>

#include <sstream>
#include <stdio.h>

int pidEmisor, pidReceptor;

void lanzarCC(int id) {
	char arg[20];
	int pid;

	sprintf(arg, "%i", id);

	pid = fork();
	if (pid == 0) {
		execl("./conexBrokerCliente", "conexBrokerCliente", arg, "E", NULL);
		syslog(LOG_ERR, "Error al lanzar proceso de conexion con Test IPC\n");
		exit(EXIT_FAILURE);
	}
	pidEmisor = pid;

	pid = fork();
	if (pid == 0) {
		execl("./conexBrokerCliente", "conexBrokerCliente", arg, "R", NULL);
		syslog(LOG_ERR, "Error al lanzar proceso de conexion con  Test IPC\n");
		exit(EXIT_FAILURE);
	}
	pidReceptor = pid;
}

void terminarCC() {
	kill(pidEmisor, SIGTERM);
	kill(pidReceptor, SIGTERM);
}

int main(int argc, char** argv) {

	int errores = 0;

	int idCliente;
	int idBroker;
	ServidorRemoto serv;

	idCliente = serv.pedirIdAdministrador();
	idBroker = serv.idBrokerConectado();

	lanzarCC(idCliente);


	printf("Haciendo Pruebas en Parque( sem y shm).\n\n");

	SemaforoRemoto sem(ID_MUTEX_PARQUE, idCliente, idBroker);
	MemCompParque mcParque(idCliente, idBroker);

	int cant = 12;

	sem.wait();
	mcParque.escribirCantPersonas(cant);
	sem.signal();

	int leido;

	sem.wait();
	leido = mcParque.leerCantPersonas();
	sem.signal();


	if (leido != cant) {
		printf("Error en cantidad escrita en el personas en parque, escrito: %i; leido: %i\n", cant, leido);
		errores++;
	}
	else {
		printf("[OK] Escrita correctamente cantidad de personas en parque\n");
	}



	cant = 25;

	sem.wait();
	mcParque.escribirBusesRepuesto(cant);
	sem.signal();

	sem.wait();
	leido = mcParque.leerBusesRepuesto();
	sem.signal();

	if (leido != cant) {
		printf("Error en cantidad escrita de buses de repuesto en parque, escrito: %i; leido: %i\n", cant, leido);
		errores++;
	}
	else {
		printf("[OK] Escrita correctamente cantidad de buses de repuesto en parque\n");
	}




	Tipos::EstadoBUS estBus;
	int valor;
	int id;

	printf("Haciendo Pruebas en Salas de Entrada( sem y shm).\n\n");

	for (int numSala = 1 ; numSala < CANT_ENTRADAS+1 ; ++numSala ) {

		printf("Pruebas en Sala Entrada %i.\n", numSala);

		MemCompSala mcSalaEnt(idCliente, idBroker, ID_SHM_SALA_ENT(numSala));
		SemaforoRemoto semSalaEnt(ID_MUTEX_SALA_ENT(numSala), idCliente, idBroker);

		mcSalaEnt.escribirCantReservas(0);
		mcSalaEnt.escribirCantPersonas(0);
		mcSalaEnt.escribirEstadoBus(Tipos::BUS_ACTIVO);

		for (int i = 0; i < CANTMAX ; ++i) {
			semSalaEnt.wait();
			mcSalaEnt.escribirPersona(i, i + 100);
			mcSalaEnt.escribirCantPersonas( mcSalaEnt.leerCantPersonas() + 1);
			mcSalaEnt.escribirCantReservas( mcSalaEnt.leerCantReservas() + 1);
			semSalaEnt.signal();
		}

		valor = mcSalaEnt.leerCantReservas();
		if ( valor != CANTMAX) {
			printf("Error en al cantidad de reservas de sala %i de entrad. Esperado: %i , Recibido: %i\n", numSala, CANTMAX, valor);
			errores++;
		}

		valor = mcSalaEnt.leerCantPersonas();
		if ( valor != CANTMAX) {
			printf("Error en al cantidad de Personas en la Sala %i de entrad. Esperado: %i , Recibido: %i\n", numSala, CANTMAX, valor);
			errores++;
		}

		for (int i = 0; i < CANTMAX ; ++i) {
			semSalaEnt.wait();
			mcSalaEnt.leerPersona(i, id);

			if ( id != (i+100) ) {
				printf("Error en obtener id de persona en sala %i de entrada. Esperado: %i, Recibido: %i\n", numSala, i+100, id);
				errores++;
			}

			semSalaEnt.signal();
		}

		mcSalaEnt.leerEstadoBUS(estBus);
		if (estBus != Tipos::BUS_ACTIVO) {
			printf("Error en el estado de bus en la sala de Zoo.\n");
			errores++;
		}
	}
	//////////////////////////////////////////////////////////////////////////////////////////////

	printf("Haciendo Pruebas en Salas De Zoo ( sem y shm).\n\n");

	for (int numSala = 1; numSala < CANT_ENTRADAS+1 ; ++numSala) {
		printf("Pruebas en Sala Zoo %i.\n", numSala);

		MemCompSala mcSalaZoo(idCliente, idBroker, ID_SHM_SALA_ZOO(numSala));
		SemaforoRemoto semSalaZoo(ID_MUTEX_SALA_ZOO(numSala),idCliente, idBroker);


		mcSalaZoo.escribirCantReservas(0);
		mcSalaZoo.escribirCantPersonas(0);
		mcSalaZoo.escribirEstadoBus(Tipos::BUS_BAJANDO_PERS);

		for (int i = 0; i < CANTMAX ; ++i) {
			semSalaZoo.wait();
			mcSalaZoo.escribirPersona(i, i + 100);
			mcSalaZoo.escribirCantPersonas( mcSalaZoo.leerCantPersonas() + 1);
			mcSalaZoo.escribirCantReservas( mcSalaZoo.leerCantReservas() + 1);
			semSalaZoo.signal();
		}

		valor = mcSalaZoo.leerCantReservas();
		if ( valor != CANTMAX) {
			printf("Error en al cantidad de reservas de sala %i de Zoo. Esperado: %i , Recibido: %i\n", numSala, CANTMAX, valor);
			errores++;
		}

		valor = mcSalaZoo.leerCantPersonas();
		if ( valor != CANTMAX) {
			printf("Error en al cantidad de Personas en la Sala %i de Zoo. Esperado: %i , Recibido: %i\n", numSala, CANTMAX, valor);
			errores++;
		}

		for (int i = 0; i < CANTMAX ; ++i) {
			semSalaZoo.wait();
			mcSalaZoo.leerPersona(i, id);

			if ( id != (i+100) ) {
				printf("Error en obtener id de persona en sala %i de Zoo. Esperado: %i, Recibido: %i\n", numSala, i+100, id);
				errores++;
			}

			semSalaZoo.signal();
		}

		mcSalaZoo.leerEstadoBUS(estBus);

		if (estBus != Tipos::BUS_BAJANDO_PERS) {
			printf("Error en el estado de bus en la sala %i de Zoo.\n", numSala);
			errores++;
		}
	}

	if (errores > 0) {
		printf("\n***Errores Totales: %i\n", errores);
	}
	else {
		printf("[OK] Prueba sin errores.\n");
	}

	//terminarCC();
	mcParque.cerrarConexion();

	return 0;
}
